package org.apache.ocean;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.index.Term;

/**
 * 
 * @author jasonr
 */
public class SearchRequestUtil {
	String defaultField;
	HttpServletRequest request;
	IndexSchema indexSchema;
	SearchRequest searchRequest;

	public SearchRequestUtil(HttpServletRequest request, IndexSchema indexSchema) {
		this.request = request;
		this.indexSchema = indexSchema;
		defaultField = indexSchema.getDefaultSearchFieldName();
		searchRequest = new SearchRequest();
	}

	public SearchRequest getSearchRequest() throws Exception {
		String type = request.getParameter("type");
		if (StringUtils.equals("id", type)) {
			String[] idVersionArray = request.getParameterValues("id");
			List<IDVersion> idVersions = null;
			if (idVersions != null) {
				idVersions = new ArrayList<IDVersion>(idVersionArray.length);
				for (int x = 0; x < idVersionArray.length; x++) {
					String[] split = StringUtils.split(idVersionArray[x], ":");
					IDVersion idVersion = new IDVersion();
					idVersion.id = new CLong(split[0]);
					idVersion.version = new CLong(split[1]);
					idVersion.shardID = split[2];
					idVersions.add(idVersion);
				}
			}
			searchRequest.lookupIDVersions = idVersions;
			return searchRequest;
		}
		searchRequest.highlightRequest = getHighlightRequest();
		handleFacets();
		handleDistance();
		handleTermFrequencies();
		searchRequest.start = ClusterUtil.parseLong(request.getParameter("start"));
		searchRequest.rows = ClusterUtil.parseLong(request.getParameter("rows"));

		if (StringUtils.equals(type, "dismax")) {
			handleDismax();
		} else {
			String queryString = request.getParameter("q");
			if (StringUtils.isBlank(queryString)) {
				throw new Exception("q query parameters needs to be passed in "+ClusterUtil.requestToString(request));
			}
			String[] split = StringUtils.split(queryString, ";");
			searchRequest.queryString = split[0];
			if (split.length > 1)
				searchRequest.sortString = split[1];
			else {
				searchRequest.sortString = request.getParameter("sort");
			}
			searchRequest.fields = ClusterUtil.splitSortedSet(request.getParameter("fields"));
		}
		return searchRequest;
	}
  
	public void handleFacets() throws Exception {
		FacetRequest facetRequest = new FacetRequest();
		List<String> queryParameterNames = ClusterUtil.getParameters("facet.query.*", request);
		for (String queryParameterName : queryParameterNames) {
			FacetRequest.QueryFacet queryFacet = new FacetRequest.QueryFacet();
			String id = getFacetID(queryParameterName);
			String queryString = request.getParameter(queryParameterName);
			facetRequest.queryFacets.add(new FacetRequest.QueryFacet(id, queryString));
		}
		List<String> fieldParameterNames = ClusterUtil.getParameters("facet.field", request);
		for (String fieldParameterName : fieldParameterNames) {
			FacetRequest.FieldFacet fieldFacet = new FacetRequest.FieldFacet();
			String field = request.getParameter(fieldParameterName);
			facetRequest.fieldFacets.add(new FacetRequest.FieldFacet(field));
		}
		searchRequest.facetRequest = facetRequest;
	}
	
	private String getFacetID(String parameterName) throws Exception {
		String[] array = StringUtils.split(parameterName, ".");
		if (array.length == 2) return null;
		if (array.length > 2) return array[2];
		throw new Exception("problem: "+parameterName);
	}
	
	public void handleDistance() throws Exception {
		CDouble distance = ClusterUtil.parseDouble(request.getParameter("distance"));
		if (distance != null) {
			String distanceType = request.getParameter("distancetype");
			String latlong = request.getParameter("latlong");
			String[] latlongSplit = StringUtils.split(latlong, ":");
			CDouble latitude = new CDouble(latlongSplit[0]);
			CDouble longitude = new CDouble(latlongSplit[1]);
			searchRequest.distance = new Distance(latitude, longitude, distance, distanceType);
		}
	}

	private void handleDismax() throws Exception {
		request.getParameter("tie");
		request.getParameter("qf");
		request.getParameter("mm");
		request.getParameter("pf");
		request.getParameter("ps");
		request.getParameter("qs");
		request.getParameter("bq");
		request.getParameter("bf");
	}

	private void handleFilterQueries() throws Exception {
		String[] filterQueryArray = request.getParameterValues("fq");
		if (filterQueryArray != null) {
			searchRequest.filterQueryStrings = Arrays.asList(filterQueryArray);
		}
	}

	private void handleTermFrequencies() throws Exception {
		String[] termFreqArray = request.getParameterValues("termfreq");
		TermFrequencies termFrequencies = null;
		if (termFreqArray != null) {
			termFrequencies = new TermFrequencies(termFreqArray.length);
			for (String string : termFreqArray) {
				Object[] array = ClusterUtil.parseTermFreq(string);
				termFrequencies.put((Term) array[0], (AtomicLong) array[1]);
			}
		}
		searchRequest.termFrequencies = termFrequencies;
	}

	private HighlightRequest getHighlightRequest() throws Exception {
		String highlightsString = request.getParameter("highlights");
		if (StringUtils.isBlank(highlightsString))
			return null;
		HighlightRequest highlightRequest = new HighlightRequest();
		highlightRequest.highlightFields = ClusterUtil.splitSortedSet(highlightsString);
		highlightRequest.highlightSnippets = ClusterUtil.parseInteger(request.getParameter("highlight.snippets"));
		highlightRequest.pre = request.getParameter("highlight.simple.pre");
		highlightRequest.post = request.getParameter("highlight.simple.post");
		highlightRequest.fragsize = ClusterUtil.parseInteger(request.getParameter("highlight.fragsize"));
		highlightRequest.pre = request.getParameter("highlight.simple.pre");
		return highlightRequest;
	}
	/**
	 * private void handleFacets() throws Exception { boolean facet =
	 * BooleanUtils.toBoolean(request.getParameter("facet")); if (facet) {
	 * String[] facatQueryStringArray = request.getParameterValues("facet.query");
	 * FacetRequest facetRequest = new FacetRequest(); searchRequest.facetRequest =
	 * facetRequest; if (facatQueryStringArray != null) { facetRequest.queries =
	 * new ArrayList<Query>(facatQueryStringArray.length); for (String
	 * facetQueryString : facatQueryStringArray) { Query query =
	 * QueryParsing.parseQuery(facetQueryString, defaultField, indexSchema);
	 * facetRequest.queries.add(query); } } } }
	 */
}
